﻿//  Copyright (c) 2009 Ray Liang (http://www.dotnetage.com)
//  Dual licensed under the MIT and GPL licenses:
//  http://www.opensource.org/licenses/mit-license.php
//  http://www.gnu.org/licenses/gpl.html

using System.Collections.Generic;
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using DNA.Mvc.UI;
using System.Web.Security;

namespace DNA.Mvc.Controllers
{
    /// <summary>
    /// 
    /// </summary>
    public partial class WidgetController
    {
        [Widget("Favorites", "Gerenate the a link list for favorites",
            ShowBorder = true,
            ShowHeader = true,
            ImageUrl = "images/favorite.png",
            IconUrl = "images/favorite_16.png"
         )]
        [Property("LinkList")]
        public ActionResult Favorites(string linkList)
        {
            if (!string.IsNullOrEmpty(linkList))
            {
                var serializer = new JavaScriptSerializer();
                ViewData.Model = serializer.Deserialize<List<NavigatableNode>>(linkList);
            }
            return PartialView();
        }

        [Widget("UserInfo",
            Description = "Display the user public information.",
            ShowHeader = true,
            ShowBorder = true,
            ImageUrl = "images/user.png",
            IconUrl = "images/user_16.png"
             )]
        [Property("UserName")]
        public ActionResult UserInfo(string userName)
        {
            var user = _context.Web.Owner;
            if (!string.IsNullOrEmpty(userName))
                user = userName;

            ViewData.Model = System.Web.Security.Membership.GetUser(user).GetProfile();
            return PartialView();
        }

        [Widget("WhoIsOnline",
            Description = "Display the statistics information of the website.",
             ImageUrl = "~/Content/Images/Widgets/users.png",
             IconUrl = "~/Content/Images/Widgets/users_16.png"
            )]
        [Property("Minutes", DisplayName = "Minutes since last in active",
            PropertyControl = ControlTypes.Number,
            ValueType = typeof(int), DefaultValue = 20)]
        public ActionResult WhoIsOnline(int minutes)
        {
            var srv = DependencyResolver.Current.GetService<DNA.Mvc.Management.IWebStatRepository>();
            var web = _context.Web;
            var stat = srv.GetStatistics(web.IsRoot ? "" : web.Name, minutes);

            if (stat.Visitors > web.MostOnlineUserCount)
            {
                web.MostOnlineUserCount = stat.Visitors;
                web.MostOnlined = DateTime.UtcNow;
                _context.DataContext.Webs.Update(web);
                _context.DataContext.SaveChanges();
            }

            stat.MostOnlineCount = web.MostOnlineUserCount;
            stat.MostOnlinedUtc = web.MostOnlined;
            stat.RegistedUserCount = Membership.GetAllUsers().Count;

            //var web = WebSite.Open(RouteData);
            //            ViewData.Model = web.GetStatistics(minutes);
            //ViewData["Guests"] = web.GetOnlineUsers(false, minutes);
            //ViewData["Registers"] = web.GetOnlineUsers(true, minutes);

            return PartialView(stat);
        }

        [Widget("WikiViewer",
            Description = "This widget can display the widget format file.",
            ShowBorder = false,
            ShowHeader = false,
            ImageUrl = "images/wikiviewer.png",
            IconUrl = "images/wikiviewer_16.png"
            )]
        [Property("FileUrl")]
        public ActionResult WikiViewer(string fileUrl)
        {
            if (!string.IsNullOrEmpty(fileUrl))
            {
                Uri uri = null;
                Uri.TryCreate(fileUrl, UriKind.Absolute, out uri);
                if (uri == null)
                    ViewData.ModelState.AddModelError("", "Bad uri.");

                if (!HttpContext.Request.Url.Authority.Equals(uri.Authority, StringComparison.OrdinalIgnoreCase))
                    ViewData.ModelState.AddModelError("", "The external uri is no support.");

                if (ModelState.IsValid)
                {
                    string fileName = DependencyResolver.Current.GetService<IWebResourceService>().MapPath(uri);
                    try
                    {
                        ViewData["Content"] = System.IO.File.ReadAllText(fileName);
                    }
                    catch
                    {
                        ViewData.ModelState.AddModelError("", "Read file error.");
                    }
                }
            }
            else
                ViewData.ModelState.AddModelError("", "No wiki file found.");
            return PartialView();
        }

        //    [Widget("SendMail",
        //Description = "Provides the form to get user info and send to the site admin",
        //ShowHeader = true,
        //ShowBorder = true,
        //ImageUrl = "~/Content/Images/Widgets/mail_send.png",
        //IconUrl = "~/Content/Images/Widgets/mail_send_16.png"
        //)]
        //    [Property("Receiver")]
        //    [Property("Subject")]
        //    [OutputCache(Duration = int.MaxValue, VaryByParam = "*")]
        //    public ActionResult SendMail()
        //    {
        //        return PartialView();
        //    }

        //        [Widget("Webpage list",
        //Description = "List webpages title,description and image in a list.",
        //ShowHeader = false,
        //ShowBorder = false,
        //ImageUrl = "images/wpagelist.png",
        //IconUrl = "images/wpagelist_16.png"
        //)]
        //        [Property("ParentID", ValueType = typeof(int), DefaultValue = 0)]
        //        public ActionResult WebPageList(int parentID)
        //        {
        //            return PartialView();
        //        }

        //public ActionResult SendMail()
        //{ 
        //}

        //[HttpPost]
        //public ActionResult SendMailTo(MailMessageModel mail)
        //{
        //    if (ModelState.IsValid)
        //    {
        //        var web = WebSite.Open("");

        //        if (!string.IsNullOrEmpty(web.SiteMailAccount))
        //        {
        //            StringBuilder builder = new StringBuilder();
        //            string senderName = mail.Sender + " (" + mail.SenderName + ")";
        //            builder.Append(senderName)
        //                      .Append(" contacted you thougth ")
        //                      .Append(Request.Url.Authority)
        //                      .AppendLine("The following is the message from " + senderName)
        //                      .AppendLine(mail.MailBody);
        //            mail.MailBody = builder.ToString();
        //            this.MailTo(mail);
        //            return Content("<div class='ui-state-highlight' style='padding:15px;'>The mail was sent.</div>");
        //        }
        //    }
        //    return RedirectToAction("SendMail");
        //}

        #region Administrator widgets kits.

        [Widget("ImageRotator", "Renders a image rotator.", ShowBorder = false, ShowHeader = false)]
        [Property("LinkList")]
        [Property("Height", ValueType = typeof(int), PropertyControl = ControlTypes.Number, DefaultValue = 280)]
        [Property("Width", ValueType = typeof(int), PropertyControl = ControlTypes.Number, DefaultValue = 640)]
        public ActionResult ImageRotator(string linkList)
        {
            if (!string.IsNullOrEmpty(linkList))
            {
                var serializer = new JavaScriptSerializer();
                ViewData.Model = serializer.Deserialize<List<NavigatableNode>>(linkList);
            }
            return PartialView();
        }
        #endregion

        [Widget("Albums", "Albums is a widget that helps you organize, and share your photos.",
            ImageUrl = "images/albums.png",
            IconUrl = "images/albums_16.jpg")]
        [Property("Path")]
        [Property("ImageHeight", ValueType = typeof(int), PropertyControl = ControlTypes.Number, DefaultValue = 100)]
        [Property("ImageWidth", ValueType = typeof(int), PropertyControl = ControlTypes.Number, DefaultValue = 130)]
        public ActionResult Albums(string path)
        {
            var fileInfos = new List<WebResourceInfo>();
            if (!string.IsNullOrEmpty(path))
            {
                Uri url = null;
                url = new Uri(path);
                var fileSrv = DependencyResolver.Current.GetService<IWebResourceService>();
                var uris = fileSrv.GetFiles(url);
                if (uris != null)
                {
                    foreach (var uri in uris)
                    {
                        var _info = new WebResourceInfo(uri);
                        if (_info.ContentType.StartsWith("image", StringComparison.OrdinalIgnoreCase))
                            fileInfos.Add(_info);
                    }
                }
            }
            return PartialView(fileInfos);
        }

        //[HttpGet,HttpPost]
        public ActionResult Generic(string wid, bool preview)
        {
            ViewBag.IsPreview = preview;

            Dictionary<string, PropertyDescriptor> descriptors = null;
            var contentUrl = "";

            if (!preview)
            {
                Guid id = new Guid(wid);
                WidgetInstance _widget = null;

                try
                {
                    _widget = _context.DataContext.Widgets.Find(id);
                }
                catch (Exception e)
                {
                    System.Threading.Thread.CurrentThread.Join(100);
                    _widget = _context.DataContext.Widgets.Find(id);
                }

                descriptors = GetPropertyDescriptors(_context.DataContext.WidgetDescriptors.Find(_widget.DescriptorID));// _widget.GetDescriptor());

                //TempData["WidgetInstance"] = _widget;
                ViewBag.WidgetInstance = _widget;

                var _pros = _widget.ReadUserPreferences();
                foreach (var key in _pros.Keys)
                {
                    if (descriptors.ContainsKey(key))
                        descriptors[key].Value = _pros[key];
                }
                contentUrl = _widget.ContentUrl;
                //installedPath = _widget.GetDescriptor().InstalledPath;
            }
            else
            {
                int _dId = 0;
                int.TryParse(wid, out _dId);

                if (_dId > 0)
                {
                    var dd = _context.DataContext.WidgetDescriptors.Find(_dId);
                    descriptors = GetPropertyDescriptors(dd);
                    contentUrl = dd.ContentUrl;
                }
                else
                {
                    var tmplID = Server.UrlDecode(wid);
                    var tmpl = _context.DataContext.WidgetTemplates.Find(tmplID);
                    descriptors = GetPropertyDescriptors(tmpl);
                    if (string.IsNullOrEmpty(tmpl.Content.Source))
                        contentUrl = "";
                    else
                        contentUrl = "~/content/widgets/" + tmplID.Replace("\\", "/") + "/" + tmpl.Content.Source;
                }
            }
            ViewBag.PropertyDescriptors = descriptors;

            if (string.IsNullOrEmpty(contentUrl))
                return PartialView();

            var ext = VirtualPathUtility.GetExtension(contentUrl);

            if (ext.Equals(".cshtml") || ext.Equals(".vbhtml") || ext.Equals(".ascx"))
                return PartialView(contentUrl);
            else
            {
                ViewBag.ContentUrl = contentUrl;
                return PartialView();
            }
        }

        private Dictionary<string, PropertyDescriptor> GetPropertyDescriptors(WidgetDescriptor descriptor)
        {
            return GetPropertyDescriptors(descriptor.GetTemplate());
        }

        private Dictionary<string, PropertyDescriptor> GetPropertyDescriptors(WidgetTemplate tmpl)
        {
            var descriptors = new Dictionary<string, PropertyDescriptor>();
            //Get default values
            foreach (var preference in tmpl.UserPreferences)
            {
                try
                {
                    var _type = Type.GetType(string.IsNullOrEmpty(preference.Type) ? "System.String" : preference.Type);
                    var prodescriptor = new PropertyDescriptor()
                    {
                        Name = preference.Name,
                        Value = !string.IsNullOrEmpty(preference.Value) ? Convert.ChangeType(preference.Value, _type) : _GetDefault(_type),
                        ValueType = _type
                    };

                    if (_type != null)
                    {
                        if (_type.Equals(typeof(System.Boolean)))
                        {
                            prodescriptor.PropertyControl = ControlTypes.Checkbox;
                        }

                        if (_type.Equals(typeof(System.Int16)) || _type.Equals(typeof(System.Int32)) || _type.Equals(typeof(System.Int64)) ||
                        _type.Equals(typeof(System.Decimal)) || _type.Equals(typeof(System.Double)))
                        {
                            prodescriptor.PropertyControl = ControlTypes.Number;
                        }

                        if (_type.Equals(typeof(System.DateTime)))
                        {
                            prodescriptor.PropertyControl = ControlTypes.DateTimePicker;
                        }
                    }

                    descriptors.Add(preference.Name, prodescriptor);

                }
                catch { continue; }
            }
            return descriptors;
        }

        private object _GetDefault(Type value)
        {
            if (value.Equals(typeof(int))) return 0;
            if (value.Equals(typeof(bool))) return false;
            if (value.Equals(typeof(decimal))) return 0;
            if (value.Equals(typeof(double))) return 0;
            if (value.Equals(typeof(float))) return 0;
            return null;
        }

        [HttpPut, ValidateInput(false)]
        public ActionResult Generic(string wid)
        {
            Response.AddHeader("cache-control", "no-cache");
            Dictionary<string, object> settings = new Dictionary<string, object>();
            var id = new Guid(wid);
            string idPrefix = wid.ToString().Substring(0, 5);
            var widget = _context.DataContext.Widgets.Find(id);// Service.GetWidget(id);
            var descriptors = GetPropertyDescriptors(widget.WidgetDescriptor);// widget.GetDescriptor());

            foreach (var k in descriptors.Keys)
            {
                string name = k + idPrefix;
                if (ValueProvider.ContainsPrefix(name))
                    settings.Add(k, ValueProvider.GetValue(name).ConvertTo(descriptors[k].ValueType));
            }

            if (settings != null)
            {
                IDictionary<string, object> data = ObjectHelper.ConvertObjectToDictionary(settings);
                widget.SaveUserPreferences(data);
                _context.DataContext.Widgets.Update(widget);
                ///Workaround: When save byte to image will cause validation error.
                var saved = _context.DataContext.SaveChanges(false);
            }
            return Content("OK");
        }

        public ActionResult _PreviewBox(string wid)
        {
            int _dId = 0;
            int.TryParse(wid, out _dId);

            if (_dId > 0)
            {
                return View(_context.DataContext.WidgetDescriptors.Find(_dId));
            }
            else
            {
                var tmplID = Server.UrlDecode(wid);
                var tmpl = _context.DataContext.WidgetTemplates.Find(tmplID);
                ViewBag.Template = tmpl;

                var descriptor = new WidgetDescriptor()
                {
                    Title = string.IsNullOrEmpty(tmpl.Defaults.Title) ? tmpl.Name : tmpl.Defaults.Title,
                    Description = tmpl.Description,
                    TitleLinkUrl = "",
                    IconUrl = ""
                    //IconUrl = tmpl.Icons != null ? Url.Content("~/content/widgets/" + tmplID.Replace("\\", "/") + tmpl.Icons[0].Source) : ""
                };

                if (tmpl.Icons != null && tmpl.Icons.Count > 0)
                    descriptor.IconUrl = Url.Content("~/content/widgets/" + tmplID.Replace("\\", "/") + tmpl.Icons[0].Source);

                if (tmpl.UserPreferences != null && tmpl.UserPreferences.Count > 0)
                {
                    var defaults = new Dictionary<string, object>();
                    foreach (var preference in tmpl.UserPreferences)
                    {
                        try
                        {
                            var _type = Type.GetType(string.IsNullOrEmpty(preference.Type) ? "System.String" : preference.Type);
                            defaults.Add(preference.Name, !string.IsNullOrEmpty(preference.Value) ? Convert.ChangeType(preference.Value, _type) : _GetDefault(_type));
                        }
                        catch { continue; }
                    }

                    if (defaults.Count > 0)
                    {
                        descriptor.Defaults = (new System.Web.Script.Serialization.JavaScriptSerializer()).Serialize(defaults);
                    }
                }

                return View(descriptor);
            }
        }

        public ActionResult _WidgetBox(Guid wid)
        {
            return View(_context.DataContext.Widgets.Find(wid));
        }
    }


}
